/**
 * Copyright (C) 2017 - 2020 https://github.com/joewee
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.bifrost.workflow.order;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.bifrost.constant.BonusPointsUpdatedType;
import com.bifrost.entity.CrmExceptionOrder;
import com.bifrost.entity.Customer;
import com.bifrost.entity.Order;
import com.bifrost.entity.OrderAttribute;
import com.bifrost.repository.CrmExceptionOrderRepository;
import com.bifrost.repository.OrderAttributeRepository;
import com.bifrost.service.CustomerService;
import com.bifrost.service.MemberService;
import com.bifrost.service.OrderService;
import com.bifrost.util.HttpClientUtil;
import com.bifrost.workflow.BaseActivity;
import com.bifrost.workflow.ProcessContext;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author joewee
 * @version 1.0.0
 * @Date 2018/3/22 11:58
 */
@Component("rewardsBonusPointsActivity")
public class RewardsBonusPointsActivity extends BaseActivity<ProcessContext<Order>> {
    private static final Logger LOGGER = LoggerFactory.getLogger(RewardsBonusPointsActivity.class);
    public static final int ORDER = 2000;
    @Autowired
    MemberService memberService;
    @Autowired
    CustomerService customerService;
    @Autowired
    com.bifrost.service.ProductService productService;
    @Value("${cbest.member.send.sale:#{null}}")
    private String url;
    @Value("${cbest.accessKey}")
    private String accessKey;
    @Autowired
    OrderAttributeRepository orderAttributeRepository;
    @Autowired
    OrderService orderService;
    @Autowired
    CrmExceptionOrderRepository exceptionOrderRepository;

    public RewardsBonusPointsActivity() {
        setOrder(ORDER);
    }

    @Override
    @Transactional(rollbackFor = {Exception.class})
    public ProcessContext<Order> execute(ProcessContext<Order> context) throws Exception {
        Order order = context.getSeedData();
        Customer customer = order.getCustomer();
        String localLoyaltyNo = customer.getLoyaltyCard();
        String loyaltyNo = null;
        //远程获取会员卡号
        try {
            OrderAttribute loyalty = orderAttributeRepository.findFirstByAttributeNameAndOrder(OrderAttribute.LOYALTY_NUMBER, order);
            if (loyalty == null || StringUtils.isBlank(loyalty.getAttributeValue())) {
                //不存在会员卡号
                JSONObject jsonObject = memberService.getMemberInfo(customer.getUnionId());
                int code = jsonObject.getIntValue("errCode");
                if (0 == code) {
                    JSONObject data = jsonObject.getJSONObject("data");
                    if (data.containsKey("cardno")) {
                        loyaltyNo = data.getString("cardno");
                        if (loyalty == null) {
                            loyalty = new OrderAttribute(OrderAttribute.LOYALTY_NUMBER, loyaltyNo, order);
                        } else {
                            loyalty.setAttributeValue(loyaltyNo);
                        }
                        orderAttributeRepository.save(loyalty);
                    }
                } else {
                    LOGGER.warn(jsonObject.getString("errMessage"));
                    return context;
                }
            } else {
                //存在会员卡号
                loyaltyNo = loyalty.getAttributeValue();
            }
        } catch (Exception e) {
            LOGGER.error("获取会员信息失败", e);
            return context;
        }
        if (StringUtils.isBlank(loyaltyNo)) {
            return context;
        }
        if (StringUtils.isEmpty(localLoyaltyNo)) {
            customer.setLoyaltyCard(loyaltyNo);
            customer.setUpdatedTimestamp(new Date());
            //会员重新绑定、恢复同步标识。门店会员信息重新同步到中间库
            if(Boolean.TRUE.equals(customer.getSync()))
                customer.setSync(Boolean.FALSE);
            customerService.saveCustomer(customer);
        } else if (!StringUtils.equalsIgnoreCase(localLoyaltyNo, loyaltyNo)) {
            //远程获取的会员卡号与本地不一样时解绑本地会员卡并记录到历史
            //解绑会员卡
            customerService.bindLoyaltyCard(customer, loyaltyNo);
        }
        //积分到本地
        customerService.rewardsBonusPoints(order, loyaltyNo);
        //发送销售信息到外部积分系统
        if (StringUtils.isNotEmpty(loyaltyNo)) {
            OrderAttribute attribute = null;
            try {
                attribute = orderAttributeRepository.findFirstByAttributeNameAndOrder(OrderAttribute.CRM_STATUS, order);
                if (attribute != null && OrderAttribute.SUCCESS.equals(attribute.getAttributeValue())) {
                    return context;
                }
                Map msg = orderService.buildBonusponitsMsgMapByOrder(order.getOrderId(), loyaltyNo);
                Map<String, String> header = new HashMap<>(2);
                header.put("Content-Type", "application/x-www-form-urlencoded");
                header.put("Signature", DigestUtils.md5Hex(accessKey.getBytes()).toUpperCase());
                String data =JSONObject.toJSONString(msg);
                String resultContent = HttpClientUtil.doPostJson(url, data, header);
                JSONObject result = null;
                try {
                    result = JSON.parseObject(resultContent);
                    if (!"0".equals(result.getString("errCode"))) {
                        LOGGER.error("订单发送积分系统失败：" + result.getString("errMessage"));
                        if (attribute == null) {
                            attribute = new OrderAttribute(OrderAttribute.CRM_STATUS, OrderAttribute.FAILURE, order);
                        } else {
                            attribute.setAttributeValue(OrderAttribute.FAILURE);
                        }
                        Long id =order.getOrderId();
                        CrmExceptionOrder exceptionOrder = exceptionOrderRepository.findFirstByOrderIdAndType(id, BonusPointsUpdatedType.INCREMENT);
                        if(exceptionOrder==null){
                            exceptionOrder = new CrmExceptionOrder(id,BonusPointsUpdatedType.INCREMENT,data);
                            exceptionOrder.setRemark(result.getString("errMessage"));
                            exceptionOrderRepository.save(exceptionOrder);
                        }
                    } else {
                        if (LOGGER.isDebugEnabled()) {
                            LOGGER.debug(JSON.toJSONString(msg));
                            LOGGER.debug("订单发送积分系统成功");
                        }
                        if (attribute == null) {
                            attribute = new OrderAttribute(OrderAttribute.CRM_STATUS, OrderAttribute.SUCCESS, order);
                        } else {
                            attribute.setAttributeValue(OrderAttribute.SUCCESS);
                        }
                    }
                } catch (Exception e) {
                    Long id =order.getOrderId();
                   LOGGER.error(String.format("参数：%s,结果：%s，原因：%s", JSONObject.toJSONString(msg), resultContent, e.getMessage()));
                    if (attribute == null) {
                        attribute = new OrderAttribute(OrderAttribute.CRM_STATUS, OrderAttribute.FAILURE, order);
                    } else {
                        attribute.setAttributeValue(OrderAttribute.FAILURE);
                    }
                    CrmExceptionOrder exceptionOrder = exceptionOrderRepository.findFirstByOrderIdAndType(id, BonusPointsUpdatedType.INCREMENT);
                    if(exceptionOrder==null){
                        exceptionOrder = new CrmExceptionOrder(id,BonusPointsUpdatedType.INCREMENT,data);
                        exceptionOrder.setRemark(e.getMessage());
                        exceptionOrderRepository.save(exceptionOrder);
                    }
                }
            } finally {
                if (attribute != null) {
                    orderAttributeRepository.save(attribute);
                }
            }
        }
        return context;
    }

}
